package sample.plugin.language.python.decision;

import static sample.plugin.language.python.PythonToken.*;

import com.rapid.api.lang.engine.highlight.decision.DecisionResult;
import com.rapid.api.lang.engine.highlight.token.TokenModel;

import java.util.ArrayList;
import java.util.List;

import sample.plugin.language.python.PythonState;

public class PythonBlockDecision extends PythonDecision {
    @Override
    public Iterable<DecisionResult> decide(TokenModel model, PythonState state) {
        switch (model.token) {
            default:
                if (state.currLine != model.line) {
                    state.currLine = model.line;
                    int prevCount = state.spaceCount;
                    int currCount = getCurrLineSpace(model);
                    int nextCount = getNextLineSpace(model);
                    state.spaceCount = currCount;
                    List<DecisionResult> results = new ArrayList<>();
                    if (prevCount > currCount) {
                        int delta = (prevCount - currCount) / 4;
                        for (int i = 0; i < delta; i++) {
                            DecisionResult tail = new DecisionResult();
                            tail.kind = DecisionResult.ResultKind.BLOCK_TAIL;
                            tail.content = new DecisionResult.BlockContent(true);
                            results.add(tail);
                            state.delta--;
                        }
                    }
                    if (currCount < nextCount) {
                        DecisionResult result = new DecisionResult();
                        result.kind = DecisionResult.ResultKind.BLOCK_HEAD;
                        results.add(result);
                        state.delta++;
                    }
                    return results;
                }
                break;
            case EOF:
                if (state.delta > 0) {
                    List<DecisionResult> results = new ArrayList<>();
                    for (int i = 0; i < state.delta; i++) {
                        DecisionResult tail = new DecisionResult();
                        tail.kind = DecisionResult.ResultKind.BLOCK_TAIL;
                        tail.content = new DecisionResult.BlockContent(true);
                        results.add(tail);
                        state.delta--;
                    }
                    return results;
                }
                break;
            case WHITESPACE:
            case TAB:
                break;
            case NEWLINE:
                /*if (state.stopLine != null && state.stopLine.line == model.line) {
                    List<DecisionResult> results = new ArrayList<>();
                    for (int i = 0; i < state.delta; i++) {
                        DecisionResult result = new DecisionResult();
                        result.kind = DecisionResult.ResultKind.BLOCK_TAIL;
                        result.content = new DecisionResult.BlockContent(true);
                        results.add(result);
                    }
                    return results;
                }*/
                break;
        }
        return refuse();
    }

    private int getCurrLineSpace(TokenModel model) {
        int count = 0;
        TokenModel prev = model.prev;
        while (prev != null) {
            if (prev.token == WHITESPACE) {
                count++;
            } else if (prev.token == TAB) {
                count += 4;
            } else {
                break;
            }
            prev = prev.prev;
        }
        return count;
    }

    private int getNextLineSpace(TokenModel model) {
        int count = 0;
        TokenModel node = model.next;
        while (node != null) {
            if (node.token == NEWLINE) {
                node = node.next;
                break;
            }
            node = node.next;
        }
        while (node != null) {
            if (node.token == WHITESPACE) {
                count++;
            } else if (node.token == TAB) {
                count += 4;
            } else {
                break;
            }
            node = node.next;
        }
        return count;
    }
}
